Read data
# Formants
formants <- readRDS("./data/dataframes/formants.rds")
# VOT
vot <- readRDS("./data/dataframes/vot.rds")
# stress
stress <- readRDS("./data/dataframes/stress.rds")
# f0
f0 <- readRDS("./data/dataframes/f0.rds")
# Intonation
syl_f0 <- readRDS("./data/dataframes/syl_f0.rds")
# CoG
dft_l <- readRDS("./data/dataframes/spect_dft_l.rds")
moments <- readRDS("./data/dataframes/spect_moments.rds")
# UTI
uti_laterals <- readRDS("./data/dataframes/uti-laterals.rds")
uti_vowels <- readRDS("./data/dataframes/uti-vowels.rds")
uti_palate <- readRDS("./data/dataframes/uti-palate.rds")
# Rhotics
rhos <- read_csv("data/varia/rhotics-impression.csv") %>%
pivot_longer(s01_1:s06_3) %>%
drop_na(value) %>%
mutate(
word_pos = factor(word_pos, levels = c("initial", "medial", "final"))
) %>%
filter(value != "trill")
## Rows: 15 Columns: 18
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (18): word, word_pos, syl_pos, s01_1, s01_2, s01_3, s02_1, s02_2, s02_3,...
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Formants
# all speakers together
ggplot(formants, aes(x = F2, y = F1, col = vowel)) +
scale_x_reverse(name = "F2 (Hz)", limits = c(3500, 0)) +
scale_y_reverse(name = "F1 (Hz)", limits = c(1500, 0)) +
geom_text(aes(label = vowel), show.legend = FALSE) +
stat_ellipse(type = "t", size = 1)

ggplot(formants, aes(x = F2, y = F1, col = vowel)) +
scale_x_reverse(name = "F2 (Hz)", limits = c(3500, 0)) +
scale_y_reverse(name = "F1 (Hz)", limits = c(1500, 0)) +
geom_text(aes(label = vowel), show.legend = FALSE) +
stat_ellipse(type = "norm", size = 1)

# all speakers together, z-scored
centroids <- aggregate(cbind(F2.z,F1.z)~vowel, formants, mean)
formants %>%
ggplot(aes(x = F2.z, y = F1.z, group = vowel)) +
scale_x_reverse(name = "F2 (z-scores)", position = "top") +
scale_y_reverse(name = "F1 (z-scores)", position = "right") +
geom_point(aes(colour = vowel), alpha = 0.5) +
stat_ellipse(aes(colour = vowel), type = "norm", size = 1) +
geom_text(data = centroids, aes(V1, V2, label = vowel), size = 7) +
theme(legend.position = "none")

ggsave(here(acou_dir, "vowels-z.png"), width = 7, height = 5)
# all speakers together, z-scored
centroids <- aggregate(cbind(F2.z.hz,F1.z.hz)~vowel, formants, mean)
formants %>%
mutate(vowel = factor(vowel, levels = c("i", "e", "y", "ɜ", "a", "ɔ", "u"))) %>%
ggplot(aes(x = F2.z.hz, y = F1.z.hz, group = vowel)) +
scale_x_reverse(name = "F2 (norm Hz)", position = "top") +
scale_y_reverse(name = "F1 (norm Hz)", position = "right") +
geom_point(aes(colour = vowel), alpha = 0.5) +
stat_ellipse(aes(colour = vowel), type = "norm", size = 1) +
geom_text(data = centroids, aes(V1, V2, label = vowel), size = 7) +
scale_color_manual(values = hoiho_7) +
theme(legend.position = "none")

# annotate("polygon", x = c(1000, 400, 400, 1000), y = c(1000, 400, 1000, 1000), alpha = 0.5)
ggsave(here(acou_dir, "vowels-z-hz.png"), width = 7, height = 5)
# all speakers together, z-scored
centroids <- aggregate(cbind(F2_F1.z.hz,F1.z.hz)~vowel, formants, mean)
formants %>%
ggplot(aes(x = F2_F1.z.hz, y = F1.z.hz, group = vowel)) +
scale_x_reverse(name = "F2-F1 (norm Hz)", position = "top") +
scale_y_reverse(name = "F1 (norm Hz)", position = "right") +
geom_point(aes(colour = vowel), alpha = 0.5) +
stat_ellipse(aes(colour = vowel), type = "norm", size = 1) +
geom_text(data = centroids, aes(V1, V2, label = vowel), size = 7) +
theme(legend.position = "none") +
labs(title = "IPA-style vowel chart")

ggsave(here(acou_dir, "vowels-z-hz-ipa.png"), width = 7, height = 5)
# all speakers together, z-scored
centroids <- aggregate(cbind(F2.z.bark, F1.z.bark)~vowel, formants, mean)
formants %>%
ggplot(aes(x = F2.z.bark, y = F1.z.bark, group = vowel)) +
scale_x_reverse(name = "F2 (norm Bark)", position = "top") +
scale_y_reverse(name = "F1 (norm Bark)", position = "right") +
geom_point(aes(colour = vowel), alpha = 0.5) +
stat_ellipse(aes(colour = vowel), type = "norm", size = 1) +
geom_text(data = centroids, aes(V1, V2, label = vowel), size = 7) +
theme(legend.position = "none") +
annotate("polygon", x = c(9, 5, 5, 9), y = c(9, 5, 9, 9), alpha = 0.5)

ggsave(here(acou_dir, "vowels-z-hz-bark.png"), width = 7, height = 5)
# all speakers together, z-scored
centroids <- aggregate(cbind(F2.z.hz,F1.z.hz)~vowel, formants, mean)
formants %>%
ggplot(aes(x = F2.z.hz, y = F1.z.hz, group = vowel)) +
scale_x_continuous(name = "F2 (norm Hz log)", position = "top", trans = revlog_trans(base = 2), breaks = seq(0, 3000, by = 250)) +
scale_y_continuous(name = "F1 (norm Hz log)", position = "right", trans = revlog_trans(base = 2), breaks = seq(0, 3000, by = 250)) +
geom_point(aes(colour = vowel), alpha = 0.5) +
stat_ellipse(aes(colour = vowel), type = "norm", size = 1) +
geom_text(data = centroids, aes(V1, V2, label = vowel), size = 7) +
theme(legend.position = "none") +
annotate("polygon", x = c(1250, 500, 500, 1250), y = c(1250, 500, 1250, 1250), alpha = 0.5)

ggsave(here(acou_dir, "vowels-z-hz-log.png"), width = 7, height = 5)
# male-female side by side
ggplot(formants, aes(x = F2, y = F1, col = vowel)) +
facet_wrap( ~ gender) +
scale_x_reverse(name = "F2 (Hz)", limits = c(3500, 0)) +
scale_y_reverse(name = "F1 (Hz)", limits = c(1500, 0)) +
geom_text(aes(label = vowel), show.legend = FALSE) +
stat_ellipse(type = "t", size = 1)

ggplot(formants, aes(x = F2, y = F1, col = vowel)) +
facet_wrap( ~ gender) +
scale_x_reverse(name = "F2 (Hz)", limits = c(3500, 0)) +
scale_y_reverse(name = "F1 (Hz)", limits = c(1500, 0)) +
geom_text(aes(label = vowel), show.legend = FALSE) +
stat_ellipse(type = "norm", size = 1)

# individual speakers side by side
ggplot(formants, aes(x = F2, y = F1, col = vowel)) +
facet_wrap( ~ speaker) +
scale_x_reverse(name = "F2 (Hz)", limits = c(3500, 0)) +
scale_y_reverse(name = "F1 (Hz)", limits = c(1500, 0)) +
geom_text(aes(label = vowel), show.legend = FALSE)

VOT
vot %>%
ggplot(aes(vot)) +
geom_density() +
facet_wrap(. ~ consonant) + geom_rug()

vot %>%
filter(consonant %in% c("p", "t", "k", "b", "d", "\u261")) %>%
ggplot(aes(reorder(consonant, desc(consonant)), vot, colour = speaker)) +
geom_line(aes(group = interaction(speaker, consonant)), position = position_dodge(width = 0.5)) +
geom_point(size = 1.5, alpha = 0.9, position = position_dodge(width = 0.5), aes(group = speaker)) +
geom_hline(aes(yintercept = 0)) +
scale_y_continuous(breaks = seq(-200, 200, by = 50)) +
coord_flip() +
labs(
y = "Voice Onset Time (ms)", x = element_blank(),
caption = "Time 0 corresponds to the plosive release."
)

ggsave(here(acou_dir, "vot-jitter.svg"), width = 7, height = 5, device = svglite)
vot %>%
filter(consonant %in% c("p", "t", "k", "b", "d", "\u261")) %>%
group_by(consonant) %>%
summarise(
mean_vot = round(mean(vot, na.rm = TRUE)),
sd_vot = round(sd(vot, na.rm = TRUE)),
tokens = n()
)
## # A tibble: 6 × 4
## consonant mean_vot sd_vot tokens
## <fct> <dbl> <dbl> <int>
## 1 p 14 6 15
## 2 t 15 10 15
## 3 k 55 26 15
## 4 b -108 27 15
## 5 d -117 19 15
## 6 É¡ -106 23 15
Stress
stress %>%
ggplot(aes(syl, duration)) +
geom_line(aes(group = interaction(session, bundle)), colour = "grey") +
geom_point(aes(colour = stress)) +
facet_grid(word ~ .) +
scale_color_manual(values = hoiho_7[c(4, 1)])

ggsave(here(acou_dir, "stress-duration.png"), width = 7, height = 5)
stress %>%
ggplot(aes(syl, intensity)) +
geom_line(aes(group = interaction(session, bundle)), colour = "grey") +
geom_point(aes(colour = stress)) +
facet_grid(word ~ .) +
scale_color_manual(values = hoiho_7[c(4, 1)])

ggsave(here(acou_dir, "stress-intensity.png"), width = 7, height = 5)
stress %>%
ggplot(aes(syl, intensity_max)) +
geom_line(aes(group = interaction(session, bundle)), colour = "grey") +
geom_point(aes(colour = stress)) +
facet_grid(word ~ .) +
scale_color_manual(values = hoiho_7[c(4, 1)])

ggsave(here(acou_dir, "stress-intensity-max.png"), width = 7, height = 5)
stress %>%
ggplot(aes(syl, intensity_mean)) +
geom_line(aes(group = interaction(session, bundle)), colour = "grey") +
geom_point(aes(colour = stress)) +
facet_grid(word ~ .) +
scale_color_manual(values = hoiho_7[c(4, 1)])

ggsave(here(acou_dir, "stress-intensity-mean.png"), width = 7, height = 5)
stress %>%
ggplot(aes(syl, f0)) +
geom_line(aes(group = interaction(session, bundle)), colour = "grey") +
geom_point(aes(colour = stress)) +
facet_grid(word ~ .) +
scale_color_manual(values = hoiho_7[c(4, 1)])

ggsave(here(acou_dir, "stress-f0.png"), width = 7, height = 5)
stress %>%
ggplot(aes(syl, f0_max)) +
geom_line(aes(group = interaction(session, bundle)), colour = "grey") +
geom_point(aes(colour = stress)) +
facet_grid(word ~ .) +
scale_color_manual(values = hoiho_7[c(4, 1)])

ggsave(here(acou_dir, "stress-f0-max.png"), width = 7, height = 5)
stress %>%
ggplot(aes(syl, f0_mean)) +
geom_line(aes(group = interaction(session, bundle)), colour = "grey") +
geom_point(aes(colour = stress)) +
facet_grid(word ~ .) +
scale_color_manual(values = hoiho_7[c(4, 1)])

ggsave(here(acou_dir, "stress-f0-mean.png"), width = 7, height = 5)
stress_filt <- stress %>%
filter(
session != "s05",
!(bundle %in% c("107-flutura", "102-mulliri", "008-mulliri", "099-flutura"))
)
dur_p <- stress_filt %>%
group_by(session) %>%
mutate(duration = scale(duration)) %>%
ggplot(aes(syl, duration)) +
geom_line(aes(group = interaction(session, bundle)), colour = "grey") +
geom_point(aes(colour = stress), size = 2) +
facet_grid(word ~ .) +
scale_color_manual(values = hoiho_7[c(4, 1)]) +
labs(
x = element_blank(),
y = "Vowel duration (z-scores)",
title = "Vowel duration"
) +
theme(legend.position = "top")
int_p <- stress_filt %>%
group_by(session) %>%
mutate(intensity_max = scale(intensity_max)) %>%
ggplot(aes(syl, intensity_max)) +
geom_line(aes(group = interaction(session, bundle)), colour = "grey") +
geom_point(aes(colour = stress), size = 2) +
facet_grid(word ~ .) +
scale_color_manual(values = hoiho_7[c(4, 1)]) +
labs(
x = element_blank(),
y = "Maximum intensity (z-scores)",
title = "Maximum intensity"
) +
theme(legend.position = "none")
f0_p <- stress_filt %>%
group_by(session) %>%
mutate(f0_max = scale(f0_max)) %>%
ggplot(aes(syl, f0_max)) +
geom_line(aes(group = interaction(session, bundle)), colour = "grey") +
geom_point(aes(colour = stress), size = 2) +
facet_grid(word ~ .) +
scale_color_manual(values = hoiho_7[c(4, 1)]) +
labs(
x = "Syllable position",
y = "Maximum f0 (z-scores)",
title = "Maximum f0"
) +
theme(legend.position = "none")
dur_p + int_p + f0_p + plot_layout(ncol = 1)

ggsave("img/acoustics/stress-dur-int-f0.png", width = 5, height = 10)
Intonation
# per sentence type, speakers together
f0 %>%
ggplot(aes(norm_timepoint, f0, colour = speaker, shape = repetition)) +
geom_point(alpha = 0.5) +
geom_path() +
facet_wrap( ~ sentence) +
labs(
x = "f0 (Hz)",
y = "normalised time"
) +
theme(legend.pos = "bottom")

# per sentence type, speakers together
f0 %>%
ggplot(aes(norm_timepoint, f0, colour = speaker)) +
geom_point(size = 0.5) +
facet_grid(speaker + repetition ~ sentence) +
labs(
x = "f0 (Hz)",
y = "normalised time"
) +
theme(legend.pos = "bottom")

f0 %>%
group_by(token) %>%
mutate(f0_smooth = c(rep(NA, 10), rollmean(f0, 21), rep(NA, 10))) %>%
filter(
repetition == 2,
speaker == "s01" & sentence_type == "narrow-focus" |
speaker == "s01" & sentence_type == "polar-q" |
speaker == "s05" & sentence_type == "broad-focus" |
speaker == "s04" & sentence_type == "narrow-focus-q",
f0 > 0
) %>%
ggplot(aes(norm_timepoint, f0_smooth)) +
geom_path(aes(colour = speaker), linetype = "31", size = 1) +
geom_text(data = syl_f0, aes(norm_timepoint, 50, label = labels), size = 4) +
geom_vline(data = syl_f0, aes(xintercept = start_norm), alpha = 0.5) +
geom_vline(aes(xintercept = 1), alpha = 0.5) +
facet_wrap(. ~ sentence, ncol = 1, scales = "free_y") +
# ylim(-100, 500) +
labs(
title = "Smoothed f0 contours",
caption = "Rolling mean filter, order = 21",
x = "normalised time",
y = "f0 (Hz)"
) +
theme_minimal() +
theme(
panel.grid.major.x = element_blank(),
panel.grid.minor.x = element_blank(),
panel.grid.minor.y = element_blank()
) +
coord_cartesian(clip = "off")

ggsave(here(acou_dir, "intonation.png"), width = 7, height = 5)
f0 %>%
group_by(token) %>%
mutate(f0_smooth = c(rep(NA, 10), rollmean(f0, 21), rep(NA, 10))) %>%
ggplot(aes(norm_timepoint, f0_smooth)) +
geom_path(aes(colour = speaker, linetype = speaker), size = 0.7) +
geom_text(data = syl_f0, aes(norm_timepoint, f0, label = labels), nudge_y = 55, size = 4) +
geom_vline(data = syl_f0, aes(xintercept = start_norm), alpha = 0.5) +
geom_vline(aes(xintercept = 1), alpha = 0.5) +
facet_wrap(~ sentence, ncol = 1) +
labs(
title = "Smoothed f0 contours",
caption = "Rolling mean filter, order = 21",
x = "normalised time",
y = "f0 (Hz)"
) +
ylim(50, 600) +
theme(
panel.grid.major.x = element_blank(),
panel.grid.minor.x = element_blank(),
panel.grid.minor.y = element_blank()
)
## Warning: Removed 100 row(s) containing missing values (geom_path).

ggsave(here(acou_dir, "intonation-all.png"), width = 7, height = 5)
## Warning: Removed 100 row(s) containing missing values (geom_path).
Spectral DFT and moments
Averaged spectral dft
average_dft <- dft_l %>%
group_by(consonant, freq) %>%
summarise(track_value = mean(track_value), .groups = "drop")
average_dft %>%
filter(freq < 10000) %>%
ggplot(aes(x = freq, y = track_value, colour = consonant)) +
geom_line() +
facet_wrap(~ consonant, ncol = 3)

average_dft %>%
ggplot(aes(x = freq/1000, y = track_value, colour = consonant)) +
geom_line(alpha = 0.4) +
geom_smooth(method = "gam") +
facet_wrap(~ consonant, nrow = 2) +
labs(x = "kHz", y = "dB")
## `geom_smooth()` using formula 'y ~ s(x, bs = "cs")'

average_dft %>%
filter(consonant %in% c("f", "θ", "s", "ʃ", "h")) %>%
ggplot(aes(x = freq/1000, y = track_value, colour = consonant)) +
geom_line(alpha = 0.4) +
geom_smooth(method = "gam") +
scale_color_manual(values = hoiho_7) +
facet_wrap(~ consonant, nrow = 2) +
labs(x = "kHz", y = "dB") +
theme(legend.position = "none")
## `geom_smooth()` using formula 'y ~ s(x, bs = "cs")'

ggsave(here(acou_dir, "spectra-vless.png"), width = 7, height = 5)
## `geom_smooth()` using formula 'y ~ s(x, bs = "cs")'
dft_l %>%
filter(freq < 8000, consonant %in% c("ʃ", "tʃ", "t\u33B\u283\u33B", "ʒ", "dʒ", "d\u33B\u292\u33B")) %>%
ggplot(aes(x = freq/1000, y = track_value, colour = consonant)) +
geom_line(alpha = 0.1, aes(group = bundle)) +
geom_smooth(method = "gam") +
facet_wrap(~ consonant, nrow = 2) +
labs(x = "kHz", y = "dB")
## `geom_smooth()` using formula 'y ~ s(x, bs = "cs")'

Spectral moments
moments %>%
# add phantom voiceless glottal fricative
bind_rows(tibble(labels = NA, sl_rowIdx = NA, moment_1 = NA, moment_2 = NA,
moment_3 = NA, moment_4 = NA, consonant = NA, voicing = NA, poa = NA,
manner = NA, voicing_manner = "voiced fricatives"
)) %>%
mutate(voicing_manner = factor(voicing_manner, levels = c("voiceless fricatives", "voiceless affricates", "voiced fricatives", "voiced affricates"))) %>%
ggplot(aes(consonant, moment_1)) +
geom_jitter(
aes(colour = poa), alpha = 0.8,
position = position_jitter(width = 0.1, seed = 2534)
) +
geom_violin(fill = NA) +
geom_boxplot(width = 0.1) +
facet_wrap(~ voicing_manner, scales = "free_x") +
labs(
x = element_blank(),
y = "Centre of gravity (Hz)"
) +
theme(legend.position = "none")
## Warning: Removed 1 rows containing non-finite values (stat_ydensity).
## Warning: Removed 1 rows containing non-finite values (stat_boxplot).
## Warning: Removed 1 rows containing missing values (geom_point).

ggsave(here(acou_dir, "cog.svg"), width = 7, height = 5, device = svglite)
## Warning: Removed 1 rows containing non-finite values (stat_ydensity).
## Warning: Removed 1 rows containing non-finite values (stat_boxplot).
## Warning: Removed 1 rows containing missing values (geom_point).
moments %>%
# add phantom voiceless glottal fricative
bind_rows(tibble(labels = NA, sl_rowIdx = NA, moment_1 = NA, moment_2 = NA,
moment_3 = NA, moment_4 = NA, consonant = NA, voicing = NA, poa = NA,
manner = NA, voicing_manner = "voiced fricatives"
)) %>%
mutate(voicing_manner = factor(voicing_manner, levels = c("voiceless fricatives", "voiceless affricates", "voiced fricatives", "voiced affricates"))) %>%
filter(!(poa %in% c("glottal", "labial", "dental", NA))) %>%
ggplot(aes(consonant, moment_1)) +
geom_jitter(
aes(colour = poa), alpha = 0.8,
position = position_jitter(width = 0.1, seed = 2534)
) +
geom_violin(fill = NA) +
geom_boxplot(width = 0.1) +
facet_wrap(~ voicing_manner, scales = "free_x") +
labs(
x = element_blank(),
y = "Centre of gravity (Hz)"
) +
theme(legend.position = "none")

ggsave(here(acou_dir, "cog-lingual.svg"), width = 7, height = 5, device = svglite)
moments %>%
group_by(consonant) %>%
summarise(mean = round(mean(moment_1), 0), sd = round(sd(moment_1), 0))
## # A tibble: 15 × 3
## consonant mean sd
## <fct> <dbl> <dbl>
## 1 f 4884 289
## 2 θ 5052 189
## 3 s 5715 137
## 4 ʃ 4983 209
## 5 h 4268 144
## 6 v 4368 260
## 7 ð 4419 280
## 8 z 5532 174
## 9 Ê’ 4785 233
## 10 ts 5679 228
## 11 tʃ 5117 233
## 12 t̻ʃ̻ 4888 105
## 13 dz 5594 186
## 14 dÊ’ 5104 249
## 15 d̻ʒ̻ 4832 192